package cc.jq1024.middleware.encrypt.util;

import cc.jq1024.middleware.encrypt.exception.DecryptException;
import cc.jq1024.middleware.encrypt.exception.EncryptException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * AES 加密解密
 * @author li--jiaqiang
 */
public class AES {

    /**
     * The password length must is 16
     */
    public static final String SECRET_PASSWORD = "2148660566@qqcom";

    /**
     * IV_PARAMETER_SPEC
     */
    public static final String IV_PARAMETER_SPEC = SECRET_PASSWORD;

    /**
     * <p> default algorithm/Mode/Padding. </p>
     */
    public static final String CIPHER_PROVIDER = "AES/CBC/PKCS5Padding";

    /**
     * 默认密码的加密
     *
     * @param content 字符串内容
     */
    public static String encrypt(String content) throws EncryptException {
        try {
            return aes(content, SECRET_PASSWORD.getBytes(StandardCharsets.UTF_8), Cipher.ENCRYPT_MODE,IV_PARAMETER_SPEC.getBytes(StandardCharsets.UTF_8),CIPHER_PROVIDER);
        } catch (GeneralSecurityException e) {
            throw new EncryptException(e);
        }
    }

    /**
     * 定义密码的参数加密
     *
     * @param content  字符串内容
     * @param password 密钥
     */
    public static String encrypt(String content, String password) throws EncryptException {
        try {
            return aes(content, password.getBytes(StandardCharsets.UTF_8), Cipher.ENCRYPT_MODE,IV_PARAMETER_SPEC.getBytes(StandardCharsets.UTF_8),CIPHER_PROVIDER);
        } catch (GeneralSecurityException e) {
            throw new EncryptException(e);
        }
    }

    /**
     * 默认密码、默认类型的解密
     *
     * @param content 字符串内容
     */
    public static String decrypt(String content) throws DecryptException {
        try {
            return aes(content, SECRET_PASSWORD.getBytes(StandardCharsets.UTF_8), Cipher.DECRYPT_MODE, IV_PARAMETER_SPEC.getBytes(StandardCharsets.UTF_8),CIPHER_PROVIDER);
        } catch (GeneralSecurityException e) {
            throw new DecryptException(e);
        }
    }

    /**
     * 指定密码的解密
     *
     * @param content  字符串内容
     * @param password 密钥
     */
    public static String decrypt(String content, String password) throws DecryptException {
        try {
            return aes(content, password.getBytes(StandardCharsets.UTF_8), Cipher.DECRYPT_MODE, IV_PARAMETER_SPEC.getBytes(StandardCharsets.UTF_8), CIPHER_PROVIDER);
        } catch (GeneralSecurityException e) {
            throw new DecryptException(e);
        }
    }

    private static String aes(String content, byte[] password, int mode,byte[] ivKeys ,String provider) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException {
        SecretKeySpec key = new SecretKeySpec(password, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivKeys);
        Cipher cipher = Cipher.getInstance(provider);
        cipher.init(mode, key,ivParameterSpec);
        if (mode == Cipher.ENCRYPT_MODE) {
            byte[] doFinal = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return ConvertUtils.byte2HexStr(doFinal);
        } else {
            byte[] byteContent = ConvertUtils.hexStr2Byte(content);
            return new String(cipher.doFinal(byteContent));
        }
    }

    public static void main(String[] args) throws InvalidAlgorithmParameterException, IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException, DecryptException, EncryptException {

        String aesKey = "ljq@security.key";

        System.out.println(AES.encrypt("{\n" +
                "    \"username\": \"何超\"\n" +
                "}", aesKey));
    }

}
